﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

using SeriesManager.Model;
using SeriesManager.Control;
using SeriesManager.Enum;
using SeriesManager.Extension;

using Windows.UI.Xaml.Data;
using System.Runtime.Serialization;
using Windows.UI.Xaml.Controls;
using Windows.ApplicationModel.Resources;
using SeriesManager.Core;
using System.Windows.Input;
using WinRTFramework.Common;
using WinRTFramework.Interfaces.AppStates;

namespace SeriesManager.ViewModel
{
    public sealed class EpisodeViewModel : ViewModelBase, ISupportTransientState
    {
        #region Properties

        public ICollectionView View
        {
            get;
            private set;
        }

        public string Title
        {
            get
            {
                if (this.View == null || this.View.CurrentItem == null)
                {
                    return string.Empty;
                }

                return (this.View.CurrentItem as EpisodeModel).Number + " - " + (this.View.CurrentItem as EpisodeModel).Name;
            }
        }

        public IEnumerable<IEnumerable<string>> MetaData
        {
            get
            {
                if (this.View == null || this.View.CurrentItem == null)
                {
                    return null;
                }

                var res = new ResourceLoader();
                var currentItem = (EpisodeModel)this.View.CurrentItem;

                var shortMetaData = new List<string>();
                if (currentItem.FirstAired.Date.CompareTo(new DateTime(1, 1, 1)) != 0)
                {
                    shortMetaData.Add(currentItem.FirstAired.ToString(currentItem.FirstAired.ToString(CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern)));
                }

                if (currentItem.Rating != 0.1) 
                {
                    shortMetaData.Add(res.GetString("Rating") + ": " + currentItem.Rating.ToString("0.0"));
                }

                shortMetaData.Add(res.GetString("Season") + " " + currentItem.Season.Number);

                if (currentItem.Director.Any()) 
                {
                    shortMetaData.Add(res.GetString("Director") + ": " + string.Join(", ", currentItem.Director));
                }

                if (currentItem.Writer.Any()) 
                {
                    shortMetaData.Add(res.GetString("Writer") + ": " + string.Join(", ", currentItem.Writer));
                }

                return new List<IEnumerable<string>> 
                {
                    shortMetaData,
                    currentItem.GuestStars
                };
            }
        }

        public bool OverviewVisibility
        {
            get
            {
                return this.View != null && this.View.CurrentItem != null && (this.View.CurrentItem as EpisodeModel).Overview.Any();
            }
        }

        public DelegateCommand<ItemClickEventArgs> StateCommand 
        { 
            get; 
            private set; 
        }

        #endregion

        public EpisodeViewModel()
        {
            this.StateCommand = new DelegateCommand<ItemClickEventArgs>(OnStateExecuted, OnStateCanExecute);
        }

        #region DelegateProperties

        private void OnStateExecuted(ItemClickEventArgs e)
        {
            var currentItem = (EpisodeModel)this.View.CurrentItem;
            currentItem.State = currentItem.State.Invert();
            TileManager.UpdateTile(currentItem.Season.Series.ID, currentItem.Season.Series.Unwatched.Count);
        }

        private bool OnStateCanExecute(ItemClickEventArgs e)
        {
            return this.View != null && this.View.CurrentItem != null && (this.View.CurrentItem as EpisodeModel).State != WatchState.UnAired && (this.View.CurrentItem as EpisodeModel).Season.Series.Subscription;
        }

        #endregion

        private void CurrentEpisode_Changed(object sender, object e)
        {
            base.OnPropertyChanged<string>(() => this.Title);
            base.OnPropertyChanged<IEnumerable<IEnumerable<string>>>(() => this.MetaData);
            base.OnPropertyChanged<bool>(() => this.OverviewVisibility);
            this.StateCommand.NotifyCanExecuteChanged();
        }

        public override void OnNavigatedTo(object arguments)
        {
            base.OnNavigatedTo(arguments);

            int episodeID = -1;

            if (arguments is int)
            {
                episodeID = (int)arguments;
            }
            else if (arguments is int[])
            {
                var args = (int[])arguments;
                AppX.Instance.Current = AppX.Instance.Series.FirstOrDefault(S => S.ID == args[0]);
                episodeID = args[1];
            }

            var episode = AppX.Instance.Current.GetEpisode(episodeID);
            if (episode != null)
            {
                this.View = new CollectionViewSource() { Source = episode.Season.Episodes }.View;
                base.OnPropertyChanged<ICollectionView>(() => this.View);
                this.View.CurrentChanged += CurrentEpisode_Changed;
                this.View.MoveCurrentTo(episode);
            }
        }

        public object GetTransientState()
        {
            if (this.View != null && this.View.CurrentItem != null)
            {
                return (this.View.CurrentItem as EpisodeModel).ID;
            }
            return null;
        }

        public IEnumerable<Type> GetTransientStateTypes()
        {
            yield return typeof(int);
        }

        public void UpdateTransientState(object state)
        {
            if (this.View != null)
            {
                var currentItem = this.View.FirstOrDefault(E => (E as EpisodeModel).ID == (int)state);
                if (currentItem != null)
                {
                    this.View.MoveCurrentTo(currentItem);
                }
            }
        }
    }
}
